home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / Files / PutAwayVolumes / PutAwayVolumes.c < prev   
Encoding:
Text File  |  1996-01-25  |  6.6 KB  |  304 lines  |  [TEXT/CWIE]

  1. //
  2. //    This code sample demonstrates how to send an AppleEvent to Finder to induce
  3. //    Finder to unmount a volume. IF FINDER or AT EASE IS RUNNING, this is the only
  4. //    reliable way to perform this task. Otherwise, Finder may have files open on
  5. //    the volume which prevent UnmountVol from succeeding.
  6. //
  7. //    Of course, if some other application has files open on the volume,
  8. //    UnmountVol will fail anyway, but that's a legitimate error condition.
  9. //
  10. //    Note this sample decides which volumes to unmount by examining their file
  11. //    system ID. Presently, running this sample will unmount all AppleShare volumes.
  12. //
  13. //    Complaints and kudos to:
  14. //
  15. //        Pete Gontier
  16. //        Apple Macintosh Developer Technical Support
  17. //        <gurgle@apple.com>
  18. //
  19.  
  20. #define OLDROUTINELOCATIONS        0
  21. #define OLDROUTINENAMES            0
  22. #define SystemSevenOrLater        1
  23.  
  24. #ifndef __AEREGISTRY__
  25. #    include <AERegistry.h>
  26. #endif
  27.  
  28. #ifndef __APPLEEVENTS__
  29. #    include <AppleEvents.h>
  30. #endif
  31.  
  32. #ifndef __FILES__
  33. #    include <Files.h>
  34. #endif
  35.  
  36. #ifndef __ALIASES__
  37. #    include <Aliases.h>
  38. #endif
  39.  
  40. #ifndef __LOWMEM__
  41. #    include <LowMem.h>
  42. #endif
  43.  
  44. enum
  45. {
  46.     kFileSystemID_AppleShare            = 1,
  47.     kFileSystemID_NetWareFileAccess        = 0x1BAD
  48. };
  49.  
  50. enum
  51. {
  52.     kCreatorCode_Finder = 'MACS',
  53.     kCreatorCode_AtEase = 'mfdr'
  54. };
  55.  
  56. static pascal OSErr BuildAppleEvent (const HVolumeParam *hvpp, AppleEvent *event)
  57. {
  58.     OSErr err = noErr;
  59.  
  60.     FSSpecPtr fssP = (FSSpecPtr) NewPtr (sizeof (*fssP));
  61.     if (!(err = MemError ( )))
  62.     {
  63.         if (!(err = FSMakeFSSpec (hvpp->ioVRefNum, fsRtParID, hvpp->ioNamePtr, fssP)))
  64.         {
  65.             AliasHandle aliasH;
  66.         
  67.             if (!(err = NewAlias (nil, fssP, &aliasH)))
  68.             {
  69.                 HLockHi ((Handle) aliasH);
  70.                 if (!(err = MemError ( )))
  71.                 {
  72.                     Size size = GetHandleSize ((Handle) aliasH);
  73.                     if (!(err = MemError ( )))
  74.                     {
  75.                         if (!(err = AEPutParamPtr (event,keyDirectObject,typeAlias,*aliasH,size)))
  76.                         {
  77.                             AEDescList aeDescList;
  78.                         
  79.                             if (!(err = AECreateList (nil,0,false,&aeDescList)))
  80.                             {
  81.                                 if (!(err = AEPutPtr (&aeDescList,1,typeAlias,*aliasH,size)))
  82.                                     err = AEPutParamDesc (event,keySelection,&aeDescList);
  83.                         
  84.                                 AEDisposeDesc (&aeDescList);
  85.                             }
  86.                         }
  87.                     }
  88.                 }
  89.                 DisposeHandle ((Handle) aliasH);
  90.                 if (!err) err = MemError ( );
  91.             }
  92.         }
  93.         DisposePtr ((Ptr) fssP);
  94.         if (!err) err = MemError ( );
  95.     }
  96.  
  97.     return err;
  98. }
  99.  
  100. static pascal OSErr GetCreatorOfFinderLikeProcess (OSType *processSignature)
  101. {
  102.     OSErr err = noErr;
  103.  
  104.     ProcessSerialNumber        psn        = { kNoProcess, kNoProcess };
  105.     ProcessInfoRec            pir        = { sizeof (pir), nil };
  106.  
  107.     *processSignature = 0;
  108.  
  109.     pir.processAppSpec = nil;
  110.  
  111.     for (;;)
  112.     {
  113.         err = GetNextProcess (&psn);
  114.         if (err)
  115.         {
  116.             if (err == procNotFound) err = noErr;
  117.             break;
  118.         }
  119.  
  120.         err = GetProcessInformation (&psn,&pir);
  121.         if (err) break;
  122.  
  123.         if (pir.processSignature == kCreatorCode_Finder || pir.processSignature == kCreatorCode_AtEase)
  124.         {
  125.             *processSignature = pir.processSignature;
  126.             break;
  127.         }
  128.     }
  129.  
  130.     return err;
  131. }
  132.  
  133. static pascal OSErr UnmountAndEject (short vRefNum)
  134. {
  135.     //
  136.     //    Mostly stolen from MoreFiles 1.3.1, but tweaked a little bit for
  137.     //    low stack usage, new headers, etc.
  138.     //
  139.  
  140.     OSErr error = noErr;
  141.  
  142.     HParmBlkPtr hpbp = (HParmBlkPtr) NewPtr (sizeof (*hpbp));
  143.     if (!(error = MemError ( )))
  144.     {
  145.         short driveNum;
  146.         Boolean ejected, wantsEject;
  147.         DrvQElPtr drvQElem;
  148.     
  149.         hpbp->volumeParam.ioVRefNum        = vRefNum;
  150.         hpbp->volumeParam.ioNamePtr        = NULL;
  151.         hpbp->volumeParam.ioVolIndex    = 0; // use ioVRefNum only
  152.     
  153.         error = PBHGetVInfoSync(hpbp);
  154.         if ( error == noErr )
  155.         {
  156.             if ( hpbp->volumeParam.ioVDrvInfo != 0 )
  157.             {
  158.                 /* the volume is online and not ejected */
  159.                 ejected = false;
  160.                 
  161.                 /* Get the drive number */
  162.                 driveNum = hpbp->volumeParam.ioVDrvInfo;
  163.             }
  164.             else
  165.             {
  166.                 /* the volume is ejected or offline */
  167.                 
  168.                 /* Is it ejected? */
  169.                 ejected = hpbp->volumeParam.ioVDRefNum > 0;
  170.                 
  171.                 if ( ejected )
  172.                 {
  173.                     /* If ejected, the drive number is ioVDRefNum */
  174.                     driveNum = hpbp->volumeParam.ioVDRefNum;
  175.                 }
  176.                 else
  177.                 {
  178.                     /* If offline, the drive number is the negative of ioVDRefNum */
  179.                     driveNum = (short)-(hpbp->volumeParam.ioVDRefNum);
  180.                 }
  181.             }
  182.             
  183.             /* find the drive queue element */
  184.             drvQElem = (DrvQElPtr)(LMGetDrvQHdr ( )->qHead);
  185.             while ( (drvQElem != NULL) && (drvQElem->dQDrive != driveNum) )
  186.             {
  187.                 drvQElem = (DrvQElPtr)drvQElem->qLink;
  188.             }
  189.             
  190.             if ( drvQElem != NULL )
  191.             {
  192.                 /* does the drive want an eject call */
  193.                 wantsEject = (*((Ptr)((Ptr)drvQElem - 3)) != 8);
  194.             }
  195.             else
  196.             {
  197.                 /* didn't find the drive!! */
  198.                 wantsEject = false;
  199.             }
  200.             
  201.             /* unmount the volume */
  202.             hpbp->volumeParam.ioNamePtr = NULL;
  203.             /* ioVRefNum is already filled in from PBHGetVInfo */
  204.             error = PBUnmountVol((ParmBlkPtr) hpbp);
  205.             if ( error == noErr )
  206.             {
  207.                 if ( wantsEject && !ejected )
  208.                 {
  209.                     /* eject the media from the drive if needed */
  210.                     hpbp->volumeParam.ioVRefNum = driveNum;
  211.                     error = PBEject((ParmBlkPtr) hpbp);
  212.                 }
  213.             }
  214.         }
  215.  
  216.         DisposePtr ((Ptr) hpbp);
  217.         if (!error) error = MemError ( );
  218.     }
  219.  
  220.     return ( error );
  221. }
  222.  
  223. static pascal OSErr PutAwayOneVolume (const HVolumeParam *hvpp, OSType finderLikeProcess)
  224. {
  225.     OSErr err = noErr;
  226.  
  227.     if (!finderLikeProcess)
  228.         err = UnmountAndEject (hvpp->ioVRefNum);
  229.     else
  230.     {
  231.         AEAddressDesc address;
  232.     
  233.         if (!(err = AECreateDesc (typeApplSignature, &finderLikeProcess, sizeof (finderLikeProcess), &address)))
  234.         {
  235.             AppleEvent event;
  236.     
  237.             if (!(err = AECreateAppleEvent (kAEFinderEvents,kAEPutAwaySelection,&address,kAutoGenerateReturnID,kAnyTransactionID,&event)))
  238.             {
  239.                 if (!(err = BuildAppleEvent (hvpp, &event)))
  240.                 {
  241.                     AppleEvent reply;
  242.     
  243.                     err = AESend (&event,&reply,kAENoReply,kAENormalPriority,kAEDefaultTimeout,nil,nil);
  244.                 }
  245.     
  246.                 AEDisposeDesc (&event);
  247.             }
  248.     
  249.             AEDisposeDesc (&address);
  250.         }
  251.     }
  252.  
  253.     return err;
  254. }
  255.  
  256. static pascal OSErr PutAwayVolumes (short ioVFSID)
  257. {
  258.     OSErr err = noErr;
  259.  
  260.     OSType finderLikeProcess;
  261.  
  262.     if (!(err = GetCreatorOfFinderLikeProcess (&finderLikeProcess)))
  263.     {
  264.         HParmBlkPtr hpbp = (HParmBlkPtr) NewPtr (sizeof (*hpbp));
  265.         if (!(err = MemError ( )))
  266.         {
  267.             Str27 volumeName;
  268.     
  269.             hpbp->volumeParam.ioNamePtr        = volumeName;
  270.             hpbp->volumeParam.ioVolIndex    = 1;
  271.     
  272.             for (;;)
  273.             {
  274.                 err = PBHGetVInfoSync (hpbp);
  275.                 if (err)
  276.                 {
  277.                     if (err == nsvErr) err = noErr;
  278.                     break;
  279.                 }
  280.     
  281.                 if (hpbp->volumeParam.ioVFSID == ioVFSID)
  282.                 {
  283.                     err = PutAwayOneVolume (&(hpbp->volumeParam), finderLikeProcess);
  284.                     if (err) break;
  285.                 }
  286.     
  287.                 hpbp->volumeParam.ioVolIndex += 1;
  288.             }
  289.     
  290.             DisposePtr ((Ptr) hpbp);
  291.             if (!err) err = MemError ( );
  292.         }
  293.     }
  294.  
  295.     return err;
  296. }
  297.  
  298. void main (void)
  299. {
  300.     MaxApplZone ( );
  301.     InitGraf (&(qd.thePort)); // AppleEvent Manager needs Random
  302.     (void) PutAwayVolumes (kFileSystemID_AppleShare);
  303. }
  304.